#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>

#include "core.h"
#include "log.h"

extern jmp_buf train_env;

static void ctrl_c_sighandle(int sig);

static int menu_init(struct core *p_core);
static int menu_manage(menu_func_t *p_menu, struct core *p_core);
static int show_option(struct menu *p_menu_data);
static int show_interface(struct menu *p_menu_data);

static int login_menu(struct core *p_core);/*登录界面*/
static int register_menu(struct core *p_core);/*注册界面*/
static int add_user_info_menu(struct core *p_core);/*完善用户信息界面*/
static int main_menu(struct core *p_core);/*主界面*/
static int user_info_menu(struct core *p_core);/*个人信息界面*/
static int book_return_ticket_menu(struct core *p_core);/*买票退票界面*/
static int system_exit_menu(struct core *p_core);/*退出界面*/

static int change_current_option(struct menu *p_menu_data, int input);
static void get_input_to_data(int input, char *option_data, int length);
static void show_option_data(struct option option_data);
static int option_init(struct option *p_option, int option_type,
                       int x_position, int y_position, 
                       char *name, char *p_bind_data, int length);

struct core *init(menu_func_t *p_menu_func)
{
    struct core *p_core_data = NULL;
    int count;

    if (!p_menu_func) {
        DEBUG("PARAM ERROR!\n");
    }

    signal(SIGINT, ctrl_c_sighandle);

    p_menu_func[LOGIN_MENU] = login_menu;
    p_menu_func[REGISTER_MENU] = register_menu;
    p_menu_func[ADD_USER_INFO_MENU] = add_user_info_menu;
    p_menu_func[SYSTEM_EXIT_MENU] = system_exit_menu;
    p_menu_func[MAIN_MENU] = main_menu;
    p_menu_func[USER_INFO_MENU] = user_info_menu;
    p_menu_func[BOOK_RETURN_TICKET] = book_return_ticket_menu;
    for (count = 7; count < MENU_NUM; count++) {
        p_menu_func[count] = NULL;
    }

    p_core_data = (struct core *)malloc(sizeof(struct core));
    train_ticket_init(&p_core_data->ticket_head, 
                      &p_core_data->booked_ticket_id_head);

    p_core_data->login_info_data.is_login = 0;
    login_init();
    progress_bar_init('>', 52, 5, 1);
    menu_init(p_core_data);

    return p_core_data;
}

int run(struct core *p_core, menu_func_t *p_menu_func)
{
    if (!p_core || !p_menu_func) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }

    menu_manage(p_menu_func, p_core);
 
    return 0;
}

int destroy(struct core *p_core, menu_func_t *p_menu_func)
{
    int count;

    if (!p_core || !p_menu_func) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }

    train_ticket_destroy(&p_core->ticket_head, 
                         &p_core->user_info_data, 
                         &p_core->booked_ticket_id_head);

    for (count = 0; count < MENU_NUM; count++) {
        p_menu_func[count] = NULL;
    }

    free(p_core);

    CLEAR();
    SHOW_CURSOR();
    RESET_CURSOR();

    return 0;
}

/*ctrl+c中断处理函数*/
void ctrl_c_sighandle(int sig)
{
    longjmp(train_env, 1);
}


/*菜单信息初始化*/
static int menu_init(struct core *p_core)
{
    struct menu * p_menu;
    if (!p_core) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }

    /*登录界面*/
    p_menu = &p_core->menu_data[LOGIN_MENU];
    p_menu->option_number = 6;
    p_menu->current_option = 0;
    memset(p_menu->temp, '\0', 20);
    memcpy(p_menu->title, "登录", (strlen("登录") + 1));

    /*登录界面选项0*/
    option_init(&p_menu->option[0], HAVE_DATA, 7, 23, "账号", 
                p_core->login_info_data.account, USER_ACCOUNT_LENGTH);
    /*登录界面选项1*/
    option_init(&p_menu->option[1], HAVE_DATA, 10, 23, "密码", 
                p_core->login_info_data.password,  USER_PASSWORD_LENGTH);
    /*登录界面选项2*/
    option_init(&p_menu->option[2], NO_DATA, 14, 18, "登录", NULL, 0);
    /*登录界面选项3*/
    option_init(&p_menu->option[3], NO_DATA, 14, 26, "注册", NULL, 0);
    /*登录界面选项4*/ 
    option_init(&p_menu->option[4], NO_DATA, 14, 33, "返回", NULL, 0);
    /*登录界面选项5*/ 
    option_init(&p_menu->option[5], NO_DATA, 14, 40, "退出", NULL, 0);
 

    /*注册界面*/
    p_menu = &p_core->menu_data[REGISTER_MENU];
    p_menu->option_number = 7;
    p_menu->current_option = 0;
    memset(p_menu->temp, '\0', 20);
    memcpy(p_menu->title, "注册", (strlen("注册") + 1));
     /*注册界面选项0*/
    option_init(&p_menu->option[0], HAVE_DATA, 6, 23, "昵称", 
                p_core->login_info_data.name, USER_NAME_LENGTH);
    /*注册界面选项1*/
    option_init(&p_menu->option[1], HAVE_DATA, 8, 23, "账号", 
                p_core->login_info_data.account, USER_ACCOUNT_LENGTH);
    /*注册界面选项2*/
    option_init(&p_menu->option[2], HAVE_DATA, 10, 23, "密码", 
                p_core->login_info_data.password, USER_PASSWORD_LENGTH);
    /*注册界面选项3*/
    option_init(&p_menu->option[3], HAVE_DATA, 12, 21, "重复密码", 
                p_core->menu_data[REGISTER_MENU].temp, USER_PASSWORD_LENGTH);
    /*注册界面选项4*/ 
    option_init(&p_menu->option[4], NO_DATA, 14, 22, "注册", NULL, 0);
    /*注册界面选项5*/ 
    option_init(&p_menu->option[5], NO_DATA, 14, 28, "返回", NULL, 0);
    /*注册界面选项6*/ 
    option_init(&p_menu->option[6], NO_DATA, 14, 34, "退出", NULL, 0);

    /*完善用户信息界面*/
    p_menu = &p_core->menu_data[ADD_USER_INFO_MENU];
    p_menu->option_number = 7;
    p_menu->current_option = 0;
    memset(p_menu->temp, '\0', 20);
    memcpy(p_menu->title, "完善信息", (strlen("完善信息") + 1));
    /*完善用户信息界面选项0*/
    option_init(&p_menu->option[0], HAVE_DATA, 5, 6, "年龄", 
                p_core->user_info_data.age, 4);
    /*完善用户信息界面选项1*/
    option_init(&p_menu->option[1], HAVE_DATA, 7, 6, "性别f/m", 
                p_core->user_info_data.sex, 2);
    /*完善用户信息界面选项2*/
    option_init(&p_menu->option[2], HAVE_DATA, 9, 6, "手机号", 
                p_core->user_info_data.phone_num, PHONE_NUN_LENGTH);
    /*完善用户信息界面选项3*/
    option_init(&p_menu->option[3], HAVE_DATA, 11, 6, "家庭住址", 
                p_core->user_info_data.home_address, HOME_ADDRESS_LENGTH);
    /*完善用户信息界面选项4*/ 
    option_init(&p_menu->option[4], NO_DATA, 13, 10, "确认", NULL, 0);
    /*完善用户信息界面选项5*/ 
    option_init(&p_menu->option[5], NO_DATA, 13, 18, "主菜单", NULL, 0);
    /*完善用户信息界面选项6*/ 
    option_init(&p_menu->option[6], NO_DATA, 13, 26, "退出", NULL, 0);

    /*主界面*/
    p_menu = &p_core->menu_data[MAIN_MENU];
    p_menu->option_number = 7;
    p_menu->current_option = 0;
    memset(p_menu->temp, '\0', 20);
    memcpy(p_menu->title, "火车售票系统", (strlen("火车售票系统") + 1));
    /*主界面选项0*/
    option_init(&p_menu->option[0], NO_DATA, 6, 4, "买票/退票", NULL, 0);
    /*主界面选项1*/
    option_init(&p_menu->option[1], NO_DATA, 8, 4, "个人信息", NULL, 0);
    /*主界面选项2*/ 
    option_init(&p_menu->option[2], NO_DATA, 10, 4, "登陆/注销", NULL, 0);
    /*主界面选项3*/ 
    option_init(&p_menu->option[3], NO_DATA, 12, 4, "注册", NULL, 0);
    /*主界面选项4*/ 
    option_init(&p_menu->option[4], NO_DATA, 14, 4, "退出", NULL, 0);
     /*主界面选项5*/
    option_init(&p_menu->option[5], NO_DATA, 16, 28, "上", NULL, 0);
    /*主界面选项6*/ 
    option_init(&p_menu->option[6], NO_DATA, 16, 43, "下", NULL, 0);

      /*个人信息界面*/
    p_menu = &p_core->menu_data[USER_INFO_MENU];
    p_menu->option_number = 7;
    p_menu->current_option = 0;
    memset(p_menu->temp, '\0', 20);
    memcpy(p_menu->title, "个人信息", (strlen("个人信息") + 1));

    option_init(&p_menu->option[0], HAVE_DATA, 6, 7, "年龄", 
                p_core->user_info_data.age, 4);
    option_init(&p_menu->option[1], HAVE_DATA, 8, 7, "性别", 
                p_core->user_info_data.sex, 2);
    option_init(&p_menu->option[2], HAVE_DATA, 10, 5, "手机号", 
                p_core->user_info_data.phone_num, PHONE_NUN_LENGTH);
    option_init(&p_menu->option[3], HAVE_DATA, 12, 3, "家庭住址", 
                p_core->user_info_data.home_address, HOME_ADDRESS_LENGTH);
    option_init(&p_menu->option[4], NO_DATA, 15, 4, "修改", NULL, 0);
    option_init(&p_menu->option[5], NO_DATA, 15, 10, "返回", NULL, 0);
    option_init(&p_menu->option[6], NO_DATA, 15, 16, "退出", NULL, 0);

    /*买票退票*/
    p_menu = &p_core->menu_data[BOOK_RETURN_TICKET];
    p_menu->option_number = 7;
    p_menu->current_option = 0;
    memset(p_menu->temp, '\0', 20);
    memcpy(p_menu->title, "买票/退票", (strlen("买票/退票") + 1));
    /*买票退票界面选项0*/
    option_init(&p_menu->option[0], HAVE_DATA, 5, 3, "车票ID", p_menu->temp, TICKET_ID_LENGTH);
    /*买票退票界面选项1*/
    option_init(&p_menu->option[1], NO_DATA, 7, 4, "买票", NULL, 0);
    /*买票退票界面选项2*/ 
    option_init(&p_menu->option[2], NO_DATA, 7, 10, "退票", NULL, 0);
    /*买票退票界面选项3*/ 
    option_init(&p_menu->option[3], NO_DATA, 9, 4, "返回", NULL, 0);
    /*买票退票界面选项4*/ 
    option_init(&p_menu->option[4], NO_DATA, 9, 10, "退出", NULL, 0);
    /*买票退票界面选项5*/
    option_init(&p_menu->option[5], NO_DATA, 16, 29, "上", NULL, 0);
    /*买票退票界面选项6*/ 
    option_init(&p_menu->option[6], NO_DATA, 16, 44, "下", NULL, 0);

    /*退出界面*/
    p_menu = &p_core->menu_data[SYSTEM_EXIT_MENU];
    p_menu->option_number = 2;
    p_menu->current_option = 0;
    memset(p_menu->temp, '\0', 20);
    memcpy(p_menu->title, "确定退出？", (strlen("确定退出？") + 1));
    /*退出界面选项0*/
    option_init(&p_menu->option[0], NO_DATA, 11, 10, "确定", NULL, 0);
    /*退出界面选项1*/
    option_init(&p_menu->option[1], NO_DATA, 11, 20, "取消", NULL, 0);

    return 0;
}

/*界面管理*/
static int menu_manage(menu_func_t *p_menu, struct core *p_core)
{
    enum menu_options option;

    if (!p_menu || !p_core) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }

    option = MAIN_MENU;

    while (1) {
        option = (enum menu_options)p_menu[option](p_core);

        if (option == GO_BACK_MENU)
            option = MAIN_MENU;

        if(option == SYSTEM_EXIT)
            break;
    }
	return 0;
}

/*登录界面*/
static int login_menu(struct core *p_core)
{
    int input, current_option, option_type, x, y;
    char *option_data = NULL;
    int option_data_length;
    struct login_info *p_login_info = NULL;

    if (!p_core) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }

    p_core->menu_data[LOGIN_MENU].current_option = 0;
    p_login_info = &p_core->login_info_data;

    while (1) {/*第一个while目的是刷新界面（有方向建输入时）*/
        show_interface(&p_core->menu_data[LOGIN_MENU]);/*显示界面*/

        current_option = p_core->menu_data[LOGIN_MENU].current_option;
        option_type = p_core->menu_data[LOGIN_MENU].option[current_option].option_type;
        option_data = p_core->menu_data[LOGIN_MENU].option[current_option].p_data;
        option_data_length = p_core->menu_data[LOGIN_MENU].option[current_option].data_length;

        /*根据不同的选项控制光标的位置*/
        if (option_type == HAVE_DATA) {
            x = p_core->menu_data[LOGIN_MENU].option[current_option].x_position;
            y = p_core->menu_data[LOGIN_MENU].option[current_option].y_position;
            SHOW_CURSOR();
            MOVETO(x, (int)(y+8+strlen(option_data)));
        } else {
            HIDE_CURSOR();
            MOVETO(18, 3);
        }

        while (1) {/*第二个while根据输入进行操作*/
            input = get_input();
            if (input == INPUT_UP || input == INPUT_DOWN ||
                input == INPUT_RIGHT || input == INPUT_LEFT) {
                    change_current_option(&p_core->menu_data[LOGIN_MENU], input);
                    break;
            }

            if (input == INPUT_NONE)
                continue;

            /*如果选项可以获取数据，则获取数据*/
            if (option_type == HAVE_DATA)
                get_input_to_data(input, option_data, option_data_length);

            switch (current_option) {/*有输入的选项执行回显，功能选项执行相应的功能*/

                case 0: /*账号*/
                    show_option_data(p_core->menu_data[LOGIN_MENU].option[0]);
                    break;
                case 1: /*密码*/
                    show_option_data(p_core->menu_data[LOGIN_MENU].option[1]);
                    if(input != INPUT_ENTER)
                        break;
                    else
                        MOVETO(18, 3);
                case 2: /*登录*/
                    MOVETO(18, 3);
                    if (input == INPUT_ENTER) {
                        if(user_login(p_login_info) == 1) {
                            load_user_info(p_login_info->account,
                                           &p_core->user_info_data,
                                           &p_core->booked_ticket_id_head);
                            MOVETO(17, 1);
                            progress_bar_run();
                            return MAIN_MENU;/*成功登录跳转到主界面*/
                        }
                    }
                    break;

                case 3: /*注册*/
                    if (input == INPUT_ENTER)
                        return REGISTER_MENU;
                    break;

                case 4: /*返回*/
                    if (input == INPUT_ENTER)
                        return MAIN_MENU;
                    break;

                case 5: /*退出*/
                    if (input == INPUT_ENTER)
                        return SYSTEM_EXIT_MENU;
                    break;

                default :  
                    break;
            }
        }
    }
    return 0;
}

/*注册界面*/
static int register_menu(struct core *p_core)
{
    int input, current_option, option_type, x, y;
    char *option_data = NULL;
    char *option_name = NULL;
    int option_data_length;

    if (!p_core) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }

    p_core->menu_data[REGISTER_MENU].current_option = 0;

    while (1) {/*第一个while目的是刷新界面（有方向建输入时）*/
        show_interface(&p_core->menu_data[REGISTER_MENU]);/*显示界面*/

        current_option = p_core->menu_data[REGISTER_MENU].current_option;
        option_type = p_core->menu_data[REGISTER_MENU].option[current_option].option_type;
        option_data = p_core->menu_data[REGISTER_MENU].option[current_option].p_data;
        option_data_length = p_core->menu_data[REGISTER_MENU].option[current_option].data_length;
        option_name = p_core->menu_data[REGISTER_MENU].option[current_option].name;

        /*根据不同的选项控制光标的位置*/
        if (option_type == HAVE_DATA) {
            x = p_core->menu_data[REGISTER_MENU].option[current_option].x_position;
            y = p_core->menu_data[REGISTER_MENU].option[current_option].y_position;
            SHOW_CURSOR();
            MOVETO(x, (int)(y+strlen(option_name)+strlen(option_data)));
        } else {
            HIDE_CURSOR();
            MOVETO(18, 3);
        }

        while (1) {/*第二个while根据输入进行操作*/
            input = get_input();
            if (input == INPUT_UP || input == INPUT_DOWN ||
                input == INPUT_RIGHT || input == INPUT_LEFT) {
                    change_current_option(&p_core->menu_data[REGISTER_MENU], input);
                    break;
            }

            if (input == INPUT_NONE)
                continue;

            /*如果选项可以获取数据，则获取数据*/
            if (option_type == HAVE_DATA)
                get_input_to_data(input, option_data, option_data_length);

            switch (current_option) {/*有输入的选项执行回显，功能选项执行相应的功能*/
                case 0:/*昵称*/
                    show_option_data(p_core->menu_data[REGISTER_MENU].option[0]);
                    break;

                case 1:/*账号*/
                    show_option_data(p_core->menu_data[REGISTER_MENU].option[1]);
                    break;

                case 2: /*密码*/
                    show_option_data(p_core->menu_data[REGISTER_MENU].option[2]);
                    break;

                case 3: /*重复密码*/
                    show_option_data(p_core->menu_data[REGISTER_MENU].option[3]);
                    if(input != INPUT_ENTER)
                        break;
                    else
                        MOVETO(18, 3);

                case 4: /*注册*/
                    MOVETO(18, 3);
                    if (input == INPUT_ENTER) {
                        if(strcmp(p_core->menu_data[REGISTER_MENU].option[2].p_data, 
                                  p_core->menu_data[REGISTER_MENU].option[3].p_data)) {
                            printf("两次密码输入不一样，请重输...");
                            break;
                        }
                        if(user_register(&p_core->login_info_data)) {
                            /*绑定重复密码的字符串用完就可以清空了*/
                            memset(p_core->menu_data[REGISTER_MENU].option[3].p_data, '\0', 
                                p_core->menu_data[REGISTER_MENU].option[3].data_length);
                            MOVETO(17, 1);
                            progress_bar_run();
                            return ADD_USER_INFO_MENU;
                        }
                    }
                    break;

                case 5: /*返回*/
                    if (input == INPUT_ENTER) {
                        /*返回时将输入的数据清除*/
                        option_data = p_core->menu_data[REGISTER_MENU].option[0].p_data;
                        option_data_length = p_core->menu_data[REGISTER_MENU].option[0].data_length;
                        memset(option_data, '\0', option_data_length);
                        option_data = p_core->menu_data[REGISTER_MENU].option[1].p_data;
                        option_data_length = p_core->menu_data[REGISTER_MENU].option[1].data_length;
                        memset(option_data, '\0', option_data_length);
                        option_data = p_core->menu_data[REGISTER_MENU].option[2].p_data;
                        option_data_length = p_core->menu_data[REGISTER_MENU].option[2].data_length;
                        memset(option_data, '\0', option_data_length);
                        option_data = p_core->menu_data[REGISTER_MENU].option[3].p_data;
                        option_data_length = p_core->menu_data[REGISTER_MENU].option[3].data_length;
                        memset(option_data, '\0', option_data_length);
                        return MAIN_MENU;
                    }
                    break;

                case 6: /*退出*/
                    if (input == INPUT_ENTER)
                        return SYSTEM_EXIT_MENU;
                    break;

                default :  
                    break;
            }
        }
    }
    return 0;
}

/*完善信息界面*/
static int add_user_info_menu(struct core *p_core)
{
    int input, current_option, option_type, x, y;
    char *option_data = NULL;
    int option_data_length;
    char *option_name;

    if (!p_core) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }

    p_core->menu_data[ADD_USER_INFO_MENU].current_option = 0;

    while (1) {/*第一个while目的是刷新界面（有方向建输入时）*/
        show_interface(&p_core->menu_data[ADD_USER_INFO_MENU]);/*显示界面*/

        current_option = p_core->menu_data[ADD_USER_INFO_MENU].current_option;
        option_type = p_core->menu_data[ADD_USER_INFO_MENU].option[current_option].option_type;
        option_data = p_core->menu_data[ADD_USER_INFO_MENU].option[current_option].p_data;
        option_data_length = p_core->menu_data[ADD_USER_INFO_MENU].option[current_option].data_length;
        option_name = p_core->menu_data[ADD_USER_INFO_MENU].option[current_option].name;

        /*根据不同的选项控制光标的位置*/
        if (option_type == HAVE_DATA) {
            x = p_core->menu_data[ADD_USER_INFO_MENU].option[current_option].x_position;
            y = p_core->menu_data[ADD_USER_INFO_MENU].option[current_option].y_position;
            SHOW_CURSOR();
            MOVETO(x, (int)(y+strlen(option_name)+strlen(option_data)));
        } else {
            HIDE_CURSOR();
            MOVETO(18, 3);
        }

        while (1) {/*第二个while根据输入进行操作*/
            input = get_input();
            if (input == INPUT_UP || input == INPUT_DOWN ||
                input == INPUT_RIGHT || input == INPUT_LEFT) {
                    change_current_option(&p_core->menu_data[ADD_USER_INFO_MENU], input);
                    break;
            }

            if (input == INPUT_NONE)
                continue;

            /*如果选项可以获取数据，则获取数据*/
            if (option_type == HAVE_DATA)
                get_input_to_data(input, option_data, option_data_length);

            switch (current_option) {/*有输入的选项执行回显，功能选项执行相应的功能*/
                case 0:/*年龄*/
                    show_option_data(p_core->menu_data[ADD_USER_INFO_MENU].option[0]);
                    break;

                case 1:/*性别*/
                    show_option_data(p_core->menu_data[ADD_USER_INFO_MENU].option[1]);
                    break;

                case 2: /*手机号*/
                    show_option_data(p_core->menu_data[ADD_USER_INFO_MENU].option[2]);
                    break;


                case 3: /*家庭住址*/
                    show_option_data(p_core->menu_data[ADD_USER_INFO_MENU].option[3]);
                    break;

                case 4: /*确认*/
                    MOVETO(18, 3);
                    if (input == INPUT_ENTER) {
                        if (add_user_info(&p_core->user_info_data, 
                            p_core->login_info_data.name, 
                            p_core->login_info_data.account))
                            return MAIN_MENU;
                    }
                    break;

                case 5: /*主菜单*/
                    if (input == INPUT_ENTER)
                        return MAIN_MENU;
                    break;

                case 6: /*退出*/
                    if (input == INPUT_ENTER)
                        return SYSTEM_EXIT_MENU;
                    break;

                default :  
                    break;
            }
        }
    }
    return 0;
}

/*主界面*/
static int main_menu(struct core *p_core)
{
    int input, current_option, option_type, x, y;
    char *option_data = NULL;
    int option_data_length;
    int count = 0;
    int ticket_page = 1;
    int break_flag = 0;

    if (!p_core) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }

    p_core->menu_data[MAIN_MENU].current_option = 0;

    while (1) {/*第一个while目的是刷新界面（有方向建输入时）*/
        show_interface(&p_core->menu_data[MAIN_MENU]);/*显示界面*/

        MOVETO(6, 15);/*定位车票打印的位置*/
        display_train_ticket(&p_core->ticket_head, ticket_page, 4);
        MOVETO(16, 35);
        printf("第%d页", ticket_page);
        for (count = 4; count < 18; count++) {
            MOVETO(count, 15);
            printf("*");
        }

        MOVETO(3,3);
        if (p_core->login_info_data.is_login)
            printf("当前用户->%s", p_core->login_info_data.name);
        else 
            printf("请登录...");


        current_option = p_core->menu_data[MAIN_MENU].current_option;
        option_type = p_core->menu_data[MAIN_MENU].option[current_option].option_type;
        option_data = p_core->menu_data[MAIN_MENU].option[current_option].p_data;
        option_data_length = p_core->menu_data[MAIN_MENU].option[current_option].data_length;

        /*根据不同的选项控制光标的位置*/
        if (option_type == HAVE_DATA) {
            x = p_core->menu_data[MAIN_MENU].option[current_option].x_position;
            y = p_core->menu_data[MAIN_MENU].option[current_option].y_position;
            SHOW_CURSOR();
            MOVETO(x, (int)(y+8+strlen(option_data)));
        } else {
            HIDE_CURSOR();
            MOVETO(18, 3);
        }

        while (1) {/*第二个while根据输入进行操作*/
            input = get_input();
            if (input == INPUT_UP || input == INPUT_DOWN ||
                input == INPUT_RIGHT || input == INPUT_LEFT) {
                    change_current_option(&p_core->menu_data[MAIN_MENU], input);
                    break;
            }

            if (input == INPUT_NONE)
                continue;

            /*如果选项可以获取数据，则获取数据*/
            if (option_type == HAVE_DATA)
                get_input_to_data(input, option_data, option_data_length);

            switch (current_option) {/*有输入的选项执行回显，功能选项执行相应的功能*/
                case 0:/*买票/退票*/
                    MOVETO(18, 3);
                    if (input == INPUT_ENTER) {
                        if (p_core->login_info_data.is_login == 0) {
                            printf("您还没登陆，请先执行登陆操作！");
                            break;
                        } 

                        if (p_core->user_info_data.is_have_info == 0) {
                            printf("您还没有添加用户信息，正在为你跳转...");
                            MOVETO(17, 1);
                            progress_bar_run();
                            return ADD_USER_INFO_MENU;
                        }
                        return BOOK_RETURN_TICKET;
                    }
                    break;

                case 1: /*个人信息*/
                    MOVETO(18, 3);
                    if (input == INPUT_ENTER) {
                        if (p_core->login_info_data.is_login == 0) {
                            printf("您还没登陆，请先执行登陆操作！");
                            break;
                        } 

                        if (p_core->user_info_data.is_have_info == 0) {
                            printf("您还没有添加用户信息，正在为你跳转...");
                            MOVETO(17, 1);
                            progress_bar_run();
                            return ADD_USER_INFO_MENU;
                        }
                        return USER_INFO_MENU;
                    }
                    break;

                case 2: /*注销或登陆*/
                    if (input == INPUT_ENTER) {
                        if (p_core->login_info_data.is_login) {
                            user_logout(&p_core->login_info_data);
                            logout_user_info(&p_core->user_info_data, 
                                             &p_core->booked_ticket_id_head);
                            printf("注销成功！");
                            break_flag = 1;
                        } else
                            return LOGIN_MENU;
                    }
                    break;
                
                case 3: /*注册*/
                    MOVETO(18, 3);
                    if (input == INPUT_ENTER) {
                        if (p_core->login_info_data.is_login)
                            printf("当前已经登陆，请注销后注册！");
                        else
                        return REGISTER_MENU;
                    }
                    break;

                case 4: /*退出*/
                    if (input == INPUT_ENTER)
                        return SYSTEM_EXIT_MENU;
                    break;

                case 5: /*上*/
                    if (input == INPUT_ENTER) {
                        if (ticket_page != 1) {
                            ticket_page--;
                            break_flag = 1;
                        }
                    }
                    break;

                case 6: /*下*/
                    if (input == INPUT_ENTER) {
                        if (ticket_page != 4) {
                            ticket_page++;
                            break_flag = 1;
                        }
                    }
                    break;

                default:  
                    break;
            }
            /*如果需要重新显示界面，break_flag用来跳出第二个while(1)*/
            if (break_flag == 1) {
                break_flag = 0;
                break;
            }
        }
    }
    return 0;
}


/*个人信息界面*/
static int user_info_menu(struct core *p_core)
{
    int input, current_option, option_type, x, y;
    int count = 0;
    char *option_data = NULL;
    int option_data_length;
    char *option_name;

    if (!p_core) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }

    p_core->menu_data[USER_INFO_MENU].current_option = 0;

    while (1) {/*第一个while目的是刷新界面（有方向建输入时）*/
        show_interface(&p_core->menu_data[USER_INFO_MENU]);/*显示界面*/

        MOVETO(5, 20);/*定位车票打印的位置*/
        display_user_ticket(&p_core->booked_ticket_id_head,
                            &p_core->ticket_head);
        for (count = 4; count < 18; count++) {
            MOVETO(count, 26);
            printf("*");
        }

        current_option = p_core->menu_data[USER_INFO_MENU].current_option;
        option_type = p_core->menu_data[USER_INFO_MENU].option[current_option].option_type;
        option_data = p_core->menu_data[USER_INFO_MENU].option[current_option].p_data;
        option_data_length = p_core->menu_data[ADD_USER_INFO_MENU].option[current_option].data_length;
        option_name = p_core->menu_data[USER_INFO_MENU].option[current_option].name;

        /*根据不同的选项控制光标的位置*/
        if (option_type == HAVE_DATA) {
            x = p_core->menu_data[USER_INFO_MENU].option[current_option].x_position;
            y = p_core->menu_data[USER_INFO_MENU].option[current_option].y_position;
            SHOW_CURSOR();
            MOVETO(x, (int)(y+strlen(option_name)+strlen(option_data)));
        } else {
            HIDE_CURSOR();
            MOVETO(18, 3);
        }

        while (1) {/*第二个while根据输入进行操作*/
            input = get_input();
            if (input == INPUT_UP || input == INPUT_DOWN ||
                input == INPUT_RIGHT || input == INPUT_LEFT) {
                    change_current_option(&p_core->menu_data[USER_INFO_MENU], input);
                    break;
            }

            if (input == INPUT_NONE)
                continue;

            /*如果选项可以获取数据，则获取数据*/
            if (option_type == HAVE_DATA)
                get_input_to_data(input, option_data, option_data_length);

            switch (current_option) {/*有输入的选项执行回显*/
                case 0:/*年龄*/
                    show_option_data(p_core->menu_data[USER_INFO_MENU].option[0]);
                    break;

                case 1:/*性别*/
                    show_option_data(p_core->menu_data[USER_INFO_MENU].option[1]);
                    break;

                case 2: /*手机号*/
                    show_option_data(p_core->menu_data[USER_INFO_MENU].option[2]);
                    break;


                case 3: /*家庭住址*/
                    show_option_data(p_core->menu_data[USER_INFO_MENU].option[3]);
                    break;

                case 4: /*修改*/
                    MOVETO(18, 3);
                    if (input == INPUT_ENTER) {
                        if (change_user_info(&p_core->user_info_data, 
                                             &p_core->booked_ticket_id_head))
                            printf("修改用户信息成功！");
                    }
                    break;

                case 5: /*返回*/
                    if (input == INPUT_ENTER) {
                        /*返回时重新加载一下信息，防止改了信息没确定修改*/
                        load_user_info(p_core->login_info_data.account,
                                       &p_core->user_info_data,
                                       &p_core->booked_ticket_id_head);
                        return MAIN_MENU;
                    }
                    break;

                case 6: /*退出*/
                    if (input == INPUT_ENTER)
                        return SYSTEM_EXIT_MENU;
                    break;

                default :  
                    break;
            }
        }
    }
    return 0;
}

/*买票退票界面*/
static int book_return_ticket_menu(struct core *p_core)
{
    int input, current_option, option_type, x, y;
    char *option_data = NULL;
    int option_data_length;
    int count = 0;
    int ticket_page = 1;
    int break_flag = 0;

    if (!p_core) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }

    p_core->menu_data[BOOK_RETURN_TICKET].current_option = 0;

    while (1) {/*第一个while目的是刷新界面（有方向建输入时）*/
        show_interface(&p_core->menu_data[BOOK_RETURN_TICKET]);/*显示界面*/

        MOVETO(6, 16);/*定位车票打印的位置*/
        display_train_ticket(&p_core->ticket_head, ticket_page, 4);
        MOVETO(16, 36);
        printf("第%d页", ticket_page);
        for (count = 4; count < 18; count++) {
            MOVETO(count, 17);
            printf("*");
        }

        MOVETO(10, 2);
        for (count = 2; count < 17; count++) {
            MOVETO(10, count);
            printf("*");
        }
        MOVETO(11, 3);
         printf("已买的车票:");
        MOVETO(12, 3);
        display_user_ticket_id(&p_core->booked_ticket_id_head);

        MOVETO(3,3);
        if (p_core->login_info_data.is_login)
            printf("当前用户->%s", p_core->login_info_data.name);
        else 
            printf("请登录...");


        current_option = p_core->menu_data[BOOK_RETURN_TICKET].current_option;
        option_type = p_core->menu_data[BOOK_RETURN_TICKET].option[current_option].option_type;
        option_data = p_core->menu_data[BOOK_RETURN_TICKET].option[current_option].p_data;
        option_data_length = p_core->menu_data[BOOK_RETURN_TICKET].option[current_option].data_length;

        /*根据不同的选项控制光标的位置*/
        if (option_type == HAVE_DATA) {
            x = p_core->menu_data[BOOK_RETURN_TICKET].option[current_option].x_position;
            y = p_core->menu_data[BOOK_RETURN_TICKET].option[current_option].y_position;
            SHOW_CURSOR();
            MOVETO(x, (int)(y+8+strlen(option_data)));
        } else {
            HIDE_CURSOR();
            MOVETO(18, 3);
        }

        while (1) {/*第二个while根据输入进行操作*/
            input = get_input();
            if (input == INPUT_UP || input == INPUT_DOWN ||
                input == INPUT_RIGHT || input == INPUT_LEFT) {
                    change_current_option(&p_core->menu_data[BOOK_RETURN_TICKET], input);
                    break;
            }

            if (input == INPUT_NONE)
                continue;

            /*如果选项可以获取数据，则获取数据*/
            if (option_type == HAVE_DATA)
                get_input_to_data(input, option_data, option_data_length);

            switch (current_option) {/*有输入的选项执行回显，功能选项执行相应的功能*/
                case 0:/*车票ID*/
                    show_option_data(p_core->menu_data[BOOK_RETURN_TICKET].option[0]);
                    break;

                case 1: /*买票*/
                    if (input == INPUT_ENTER) {
                        MOVETO(18, 3);
                        if (book_train_ticket(&p_core->user_info_data,
                                          &p_core->booked_ticket_id_head,
                                          &p_core->ticket_head,
                                          p_core->menu_data[BOOK_RETURN_TICKET].temp))
                            break_flag = 1;
                    }
                    break;

                case 2: /*退票*/
                    if (input == INPUT_ENTER) {
                        MOVETO(18, 3);
                        if (return_train_ticket(&p_core->user_info_data,
                                          &p_core->booked_ticket_id_head,
                                          &p_core->ticket_head,
                                          p_core->menu_data[BOOK_RETURN_TICKET].temp))
                            break_flag = 1;
                    }
                    break;
                
                case 3: /*返回*/
                    if (input == INPUT_ENTER) {
                        /*返回时将输入的数据清除*/
                        option_data = p_core->menu_data[BOOK_RETURN_TICKET].option[0].p_data;
                        option_data_length = p_core->menu_data[BOOK_RETURN_TICKET].option[0].data_length;
                        memset(option_data, '\0', option_data_length);
                        return MAIN_MENU;
                    }
                    break;
                    
                case 4: /*退出*/
                    if (input == INPUT_ENTER)
                        return SYSTEM_EXIT_MENU;
                    break;

                case 5: /*上*/
                    if (input == INPUT_ENTER) {
                        if (ticket_page != 1) {
                            ticket_page--;
                            break_flag = 1;
                        }
                    }
                    break;

                case 6: /*下*/
                    if (input == INPUT_ENTER) {
                        if (ticket_page != 4) {
                            ticket_page++;
                            break_flag = 1;
                        }
                    }
                    break;

                default:  
                    break;
            }
            /*如果需要重新显示界面，break_flag用来跳出第二个while(1)*/
            if (break_flag == 1) {
                break_flag = 0;
                break;
            }
        }
    }
    return 0;
}

/*退出界面*/
static int system_exit_menu(struct core *p_core)
{
    int input, current_option, option_type, x, y;
    char *option_data = NULL;
    int option_data_length;

    if (!p_core) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }

    p_core->menu_data[SYSTEM_EXIT_MENU].current_option = 0;

    while (1) {/*第一个while目的是刷新界面（有方向建输入时）*/
        show_interface(&p_core->menu_data[SYSTEM_EXIT_MENU]);/*显示界面*/

        current_option = p_core->menu_data[SYSTEM_EXIT_MENU].current_option;
        option_type = p_core->menu_data[SYSTEM_EXIT_MENU].option[current_option].option_type;
        option_data = p_core->menu_data[SYSTEM_EXIT_MENU].option[current_option].p_data;
        option_data_length = p_core->menu_data[SYSTEM_EXIT_MENU].option[current_option].data_length;

        /*根据不同的选项控制光标的位置*/
        if (option_type == HAVE_DATA) {
            x = p_core->menu_data[SYSTEM_EXIT_MENU].option[current_option].x_position;
            y = p_core->menu_data[SYSTEM_EXIT_MENU].option[current_option].y_position;
            SHOW_CURSOR();
            MOVETO(x, (int)(y+8+strlen(option_data)));
        } else {
            HIDE_CURSOR();
            MOVETO(18, 3);
        }

        while (1) {/*第二个while根据输入进行操作*/
            input = get_input();
            if (input == INPUT_UP || input == INPUT_DOWN ||
                input == INPUT_RIGHT || input == INPUT_LEFT) {
                    change_current_option(&p_core->menu_data[SYSTEM_EXIT_MENU], input);
                    break;
            }

            if (input == INPUT_NONE)
                continue;

            /*如果选项可以获取数据，则获取数据*/
            if (option_type == HAVE_DATA)
                get_input_to_data(input, option_data, option_data_length);

            switch (current_option) {/*有输入的选项执行回显，功能选项执行相应的功能*/
                case 0: /*确认退出*/
                    if (input == INPUT_ENTER)
                        return SYSTEM_EXIT;/*表示从退出界面退出*/
                    break;

                case 1: /*取消退出*/
                    if (input == INPUT_ENTER)
                        return GO_BACK_MENU;
                    break;

                default :  
                    break;
            }
        }
    }
    return 0;
}

/*显示界面的选项*/
static int show_option(struct menu *p_menu_data)
{
    int count, password_count;

    if (!p_menu_data) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }

    for (count = 0; count < p_menu_data->option_number; count++) {
        MOVETO(p_menu_data->option[count].x_position, 
               p_menu_data->option[count].y_position);

        if (count == p_menu_data->current_option)
            printf(CORE_YELLOW"❥%s"CORE_NONE, p_menu_data->option[count].name);
        else
            printf(" %s", p_menu_data->option[count].name);

        if(p_menu_data->option[count].option_type == HAVE_DATA) {

            MOVETO(p_menu_data->option[count].x_position, 
                   p_menu_data->option[count].y_position + 
                   (int)strlen(p_menu_data->option[count].name));

            if(!strcmp(p_menu_data->option[count].name, "密码") ||
               !strcmp(p_menu_data->option[count].name, "重复密码")) {
                for (password_count = 0;
                     password_count < p_menu_data->option[count].data_length;
                     password_count++) {
                        if(p_menu_data->option[count].p_data[password_count] == '\0')
                            printf(" ");
                        else
                            printf("*");
                    }
            } else
                printf("%s", p_menu_data->option[count].p_data);
        }
    }

    return 0;
}

/**
 * 显示界面
 */
static int show_interface(struct menu *p_menu_data)
{
    int count;

    if (!p_menu_data) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }

    CLEAR();
    MOVETO(1, 1);
    printf("\n****************************************************************\n");
    MOVETO(3, 1);
    printf("\n****************************************************************\n");
    for (count = 2; count < 20; count++) {
        MOVETO(count, 1);
        printf("**");
    }

    MOVETO(3, 30);
    printf("%s", p_menu_data->title);   /*显示标题*/

    show_option(p_menu_data);   /*显示选项*/

    MOVETO(16, 1);
    printf("\n****************************************************************\n");
    for (count = 2; count < 20; count++) {
        MOVETO(count, 65);
        printf("**");
    }
    printf("\n******************************************************************\n");

    return 0;
}


/*获取选项*/
static int change_current_option(struct menu *p_menu_data, int input)
{
    int option = p_menu_data->current_option;

    if (!p_menu_data || !input) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }
    
    switch (input) {
            case INPUT_UP:
                option--;
                if (option < 0)
                    option = (p_menu_data->option_number - 1);
                break;
            
            case INPUT_DOWN:
                option++;
                if (option > (p_menu_data->option_number - 1))
                    option = 0;
                break;

            case INPUT_LEFT:
                option--;
                if (option < 0)
                    option = (p_menu_data->option_number - 1);
                break;

            case INPUT_RIGHT:
                option++;
                if (option > (p_menu_data->option_number - 1))
                    option = 0;
                break;
            
            default:
                break;
        }
	
	p_menu_data->current_option = option;

    return 0;
}

static void get_input_to_data(int input, char *option_data, int length)
{
    int count = 0;
    if (input != INPUT_ENTER) {

        for (count = 0; count < length; count++) {
            if (option_data[count] == '\0' ) {
                if (input == INPUT_BACKSPACE)
                    option_data[count-1] = '\0';
                else
                    option_data[count] = input;
                break;
            }
        }
    }

    option_data[length - 1] = '\0';
}

static void show_option_data(struct option option_data)
{
    int x,y;
    int count;

    x = option_data.x_position;
    y = option_data.y_position;

    MOVETO(x, (int)(y+strlen(option_data.name)));
    if(!strcmp(option_data.name, "密码") || !strcmp(option_data.name, "重复密码")) {
        for (count = 0; count < option_data.data_length; count++) {
            if(option_data.p_data[count] == '\0')
                printf(" ");
            else
                printf("*");
        }
    } else {
        for (count = 0; count < option_data.data_length; count++) {
            if(option_data.p_data[count] == '\0')
                printf(" ");
            else
                printf("%c",option_data.p_data[count]);
        }
    }
    MOVETO(x, (int)(y+strlen(option_data.name)+strlen(option_data.p_data)));
}


/*选项初始化*/
static int option_init(struct option *p_option, int option_type,
                       int x_position, int y_position, 
                       char *name, char *p_bind_data, int length)
{
    if (!p_option || !name) {
        DEBUG("PARAM ERROR!\n");
        return (-CORE_PARAM_NULL);
    }

    p_option->option_type = option_type;
    p_option->x_position = x_position;
    p_option->y_position = y_position;
    memcpy(p_option->name, name, (strlen(name) + 1));
    p_option->p_data = p_bind_data;
    p_option->data_length = length;

    return 0;
}
